package com.ck.company.service.impl;

import com.ck.common.service.OperationLogService;
import com.ck.company.service.*;
import com.ck.config.CustomProperties;
import com.ck.constant.*;
import com.ck.dao.PictureMapper;
import com.ck.exception.ServiceException;
import com.ck.model.common.OperationLog;
import com.ck.model.common.Picture;
import com.ck.model.common.User;
import com.ck.model.common.page.PageInfo;
import com.ck.model.company.dto.CpPictureListDTO;
import com.ck.model.company.vo.CpPictureListVO;
import com.ck.model.company.vo.CpProgramPictureListVO;
import com.ck.util.FileUtils;
import com.ck.util.HttpUtils;
import com.ck.util.HuaWeiCloudUtils;
import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.io.FileExistsException;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
import java.util.Map;

/**
 * 图片Service实现类
 *
 * @author dxy
 * @date 2018/7/4 9:54
 */
@Service("cpPictureService")
public class CpPictureServiceImpl implements CpPictureService {
    @Autowired
    private PictureMapper pictureMapper;
    @Autowired
    private CustomProperties customProperties;
    @Autowired
    private OperationLogService operationLogService;
    @Autowired
    private CpSceneService cpSceneService;

    /**
     * 保存图片
     *
     * @param pictureFile MultipartFile
     * @param request     HttpServletRequest
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public Map<String, Object> savePicture(MultipartFile pictureFile, HttpServletRequest request) throws IOException, ServiceException {
        Object pictureGroupId = request.getParameter("pictureGroupId");
        //获取用户的商家编码
        User loginUser = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        String companyCode = loginUser.getCompanyCode();
        //获取图片原始图片名
        String originalFilename = pictureFile.getOriginalFilename();
        //获取图片后缀
        String extension = FilenameUtils.getExtension(originalFilename);
        //没有后缀的图片名
        String fileName = originalFilename.replaceAll("." + extension, "");
        //校验图片名是否存在
        Picture oldPicture = getPictureByName(companyCode, fileName);
        //图片名已存在
        if (oldPicture != null) {
            //校验文件名是否与库中的同商家的视频文件名重复，如果重复，自动命名文件名，命名规则（a.jpg,a(1).jpg,a(2).jpg）
            //查找类型"a(1)"类似的文件，mysql匹配类型为“a(%)%”
            Long count = countPictureByName(companyCode, fileName + "(%)");
            if (count != null) {
                fileName = fileName + "(" + (count + 1) + ")";
            }
        }
        //将MultipartFile转化为指定文件名的File
        File file = FileUtils.multipartFileConvertFile(pictureFile, fileName + "." + extension);
        //将图片上传至华为云
        String url = HuaWeiCloudUtils.uploadFile2HuaweiCloud(file, companyCode + "/picture/");
        //获取图片md5值
        String md5 = FileUtils.getFileMD5(file);
        //获取图片大小
        long length = file.length();
        //把MultipartFile转化为File,会在本地创建图片，用完file后，需要删除
        if (file.exists()) {
            file.delete();
        }
        //获取图片名称
        Picture picture = new Picture();
        picture.setPictureName(fileName);
        picture.setCompanyCode(companyCode);
        picture.setMd5(md5);
        picture.setSize(length);
        picture.setAddTime(System.currentTimeMillis());
        picture.setPictureSuffix(extension);
        picture.setUrl(url);
        if (pictureGroupId != null) {
            Long pgi = Long.valueOf(pictureGroupId.toString());
            if (!pgi.equals(PictureGroupConstant.ALL_DEVICE_GROUP_ID)
                    && !pgi.equals(PictureGroupConstant.NO_DEVICE_GROUP_ID)) {
                picture.setPictureGroupId(Long.valueOf(pictureGroupId.toString()));
            }
        }
        pictureMapper.insertPicture(picture);
        Map<String, Object> pictureMap = Maps.newHashMap();
        pictureMap.put("pictureId", picture.getPictureId());
        pictureMap.put("url", url);
        pictureMap.put("md5", md5);
        pictureMap.put("size", length);
        pictureMap.put("file", url);
        pictureMap.put("pictureName", fileName);
        pictureMap.put("pictureSuffix", extension);

        //记录操作日志
        OperationLog operationLog = new OperationLog();
        operationLog.setCopmanyCode(companyCode);
        operationLog.setOperationContent("保存图片,图片ID为:" + picture.getPictureId());
        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
        operationLog.setOperationTime(System.currentTimeMillis());
        operationLog.setOperationModule(ModuleConstant.MODULE_MATERIAL + "-" + ModuleConstant.MODULE_PICTURE);
        operationLog.setRealname(loginUser.getRealname());
        operationLog.setUserName(loginUser.getUserName());
        operationLog.setOperationIp(HttpUtils.getRemortIP(request));
        operationLogService.saveOperationLog(operationLog);
        return pictureMap;
    }

    /**
     * 重命名
     *
     * @param pictureId      图片ID
     * @param picutreNewName 图片新名称
     * @param request        HttpServletRequest
     * @throws ServiceException
     * @throws IOException
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void renamePicture(Long pictureId, String picutreNewName, HttpServletRequest request) throws ServiceException, IOException {
        User loginUser = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        if (pictureId == null) {
            throw new ServiceException("图片ID为空，请联系管理员");
        }
        Picture oldPicture = pictureMapper.getPictureById(pictureId);
        if (oldPicture == null) {
            throw new ServiceException("图片不存在，请联系管理员");
        }
        //图片临时存放目录
        String fileTempSaveDir = customProperties.getFileTempSaveDir();
        String separator = File.separator;
        if (!fileTempSaveDir.endsWith(separator)) {
            fileTempSaveDir = fileTempSaveDir + separator;
        }
        String pictureSuffix = oldPicture.getPictureSuffix();
        String url = oldPicture.getUrl();
        String pictureName = oldPicture.getPictureName();
        String filePath = fileTempSaveDir + pictureName + "." + pictureSuffix;
        //下载源图片图片
        FileUtils.downloadFileFromURL(url, filePath);
        //从url中获取图片原始名称
        //重命名图片
        Path path = Paths.get(filePath);
        String fullNewName = picutreNewName + "." + pictureSuffix;
        try {
            Files.move(path, path.resolveSibling(fullNewName));
        } catch (FileExistsException e1) {
            // TODO 本地环境时，如果重名后的文件已存在，会报错，这里将源文件删除
            e1.printStackTrace();
            File fileNew = new File(path.resolveSibling(fullNewName).toUri());
            if (fileNew.exists()) {
                fileNew.delete();
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        //将重命名的图片上传至华为云
        File file = new File(fileTempSaveDir + fullNewName);
        String companyCode = oldPicture.getCompanyCode();
        Picture newPicture = new Picture();
        if (file.exists()) {
            url = HuaWeiCloudUtils.uploadFile2HuaweiCloud(file, companyCode + "/picture/");
            newPicture.setUrl(url);
            //删除本地临时图片
            file.delete();
        }
        newPicture.setPictureName(picutreNewName);
        newPicture.setPictureId(pictureId);
        pictureMapper.updatePictureById(newPicture);
        //记录操作日志
        OperationLog operationLog = new OperationLog();
        operationLog.setCopmanyCode(companyCode);
        operationLog.setOperationContent("重命名图片,图片ID为:" + pictureId);
        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
        operationLog.setOperationTime(System.currentTimeMillis());
        operationLog.setOperationModule(ModuleConstant.MODULE_MATERIAL + "-" + ModuleConstant.MODULE_PICTURE);
        operationLog.setRealname(loginUser.getRealname());
        operationLog.setUserName(loginUser.getUserName());
        operationLog.setOperationIp(HttpUtils.getRemortIP(request));
        operationLogService.saveOperationLog(operationLog);
    }

    /**
     * 图片列表
     *
     * @param companyCode 商家编码
     * @param pictureName 图片名称
     * @param pageNum     当前页
     * @param pageSize    每页显示条数
     * @return List<CpPictureListVO>
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public PageInfo<CpPictureListVO> listPicture(String companyCode, String pictureName, Integer pageNum, Integer pageSize) {
        //设置默认值
        if (pageNum == null) {
            pageNum = PageConstant.DEFAULT_PAGE_NUM;
        }
        if (pageSize == null) {
            pageSize = PageConstant.DEFAULT_PAGE_SIZE;
        }
        PageHelper.startPage(pageNum, pageSize);
        Page<CpPictureListDTO> page = pictureMapper.listPicture(companyCode, pictureName);
        PageInfo<CpPictureListVO> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotal(page.getTotal());

        List<CpPictureListVO> voList = Lists.newArrayList();
        List<CpPictureListDTO> dtoList = page.getResult();
        for (CpPictureListDTO dto : dtoList) {
            CpPictureListVO vo = new CpPictureListVO();
            vo.setPictureName(dto.getPictureName());
            vo.setCompanyCode(dto.getCompanyCode());
            vo.setUrl(dto.getUrl());
            vo.setPictureId(dto.getPictureId());
            voList.add(vo);
        }
        pageInfo.setList(voList);
        return pageInfo;
    }

    /**
     * 通过图片ID删除图片
     *
     * @param pictureId 图片ID
     * @param request   HttpServletRequest
     * @throws ServiceException
     * @throws IOException
     */
    @Override
    @Transactional(readOnly = false, rollbackFor = Exception.class)
    public void deletePictureById(Long pictureId, HttpServletRequest request) throws ServiceException, IOException {
        //如果已在节目中存在，不能删除图片
        Picture picture = pictureMapper.getPictureById(pictureId);
        if (picture == null) {
            throw new ServiceException("图片信息不存在，请联系管理员");
        }
        //登录用户
        User loginUser = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        //商家编码
        String companyCode = loginUser.getCompanyCode();
        String url = picture.getUrl();
        //地址
        if (StringUtils.isNotBlank(url)) {
            //校验视频是否被使用，具体验证逻辑，请查看SQL语句
            Long count = cpSceneService.countNoDeleteProgram(url);
            if (count > 0) {
                throw new ServiceException("图片正在被使用，不能删除");
            }
            //删除华为云上对应的图片
            String fileKey = companyCode + "/picture/" + picture.getPictureName() + "." + picture.getPictureSuffix();
            HuaWeiCloudUtils.deleteHuaweiCloudObject(fileKey);
        }
        //删除数据库中的图片数据
        pictureMapper.deletePictureById(pictureId);
        //记录操作日志
        OperationLog operationLog = new OperationLog();
        operationLog.setCopmanyCode(companyCode);
        operationLog.setOperationContent("删除图片,图片ID为::" + pictureId);
        operationLog.setOperationStatus(BusinessConstant.OPERATION_LONG_OPERATION_STATUS_SUCCESS);
        operationLog.setOperationTime(System.currentTimeMillis());
        operationLog.setOperationModule(ModuleConstant.MODULE_MATERIAL + "-" + ModuleConstant.MODULE_PICTURE);
        operationLog.setRealname(loginUser.getRealname());
        operationLog.setUserName(loginUser.getUserName());
        operationLog.setOperationIp(HttpUtils.getRemortIP(request));
        operationLogService.saveOperationLog(operationLog);
    }

    /**
     * 通过图片组ID获取图片数量
     *
     * @param pictureGroupId 图片组ID
     * @param companyCode    商家编码
     * @return Long(图片数量)
     */
    @Override
    @Transactional(readOnly = true, rollbackFor = Exception.class)
    public Long countPictureByPictureGroupId(Long pictureGroupId, String companyCode) {
        return pictureMapper.countPictureByPictureGroupId(pictureGroupId, companyCode);
    }

    /**
     * 更新图片分组ID
     *
     * @param pictureGroupId 图片分组ID
     * @param pictureId      图片ID
     */
    @Override
    public void updatePictureGroupId(Long pictureGroupId, Long pictureId) throws ServiceException {
        if (pictureId == null) {
            throw new ServiceException("图片ID不能为空");
        }
        if (pictureGroupId != null) {
            if (pictureGroupId.equals(PictureGroupConstant.ALL_DEVICE_GROUP_ID)
                    || pictureGroupId.equals(PictureGroupConstant.NO_DEVICE_GROUP_ID)) {
                pictureGroupId = null;
            }
        }
        pictureMapper.updatePictureGroupId(pictureGroupId, pictureId);
    }

    /**
     * 节目选择图片列表
     *
     * @param companyCode    公司代码
     * @param pictureGroupId 图片组ID
     * @param pageNum        当前页
     * @param pageSize       每页条数
     * @return PageInfo
     */
    @Override
    public Page<CpProgramPictureListVO> listProgramPicture(String companyCode, Long pictureGroupId, Integer pageNum, Integer pageSize) {
        PageHelper.startPage(pageNum, pageSize);
        return pictureMapper.listProgramPicture(companyCode, pictureGroupId);
    }

    /**
     * 通过图片名称获取图片
     *
     * @param companyCode 商家编码
     * @param pictureName 图片名称
     * @return Picture
     */
    @Override
    public Picture getPictureByName(String companyCode, String pictureName) throws ServiceException {
        if (StringUtils.isBlank(companyCode) || StringUtils.isBlank(pictureName)) {
            throw new ServiceException("输入参数不能为空");
        }
        return pictureMapper.getPictureByName(companyCode, pictureName);
    }

    /**
     * 获取图片名称类似的条数
     *
     * @param companyCode 商家编码
     * @param pictureName 图片名称
     * @return Long(图片条数)
     * @throws ServiceException
     */
    @Override
    public Long countPictureByName(String companyCode, String pictureName) throws ServiceException {
        if (StringUtils.isBlank(companyCode) || StringUtils.isBlank(pictureName)) {
            throw new ServiceException("输入参数不能为空");
        }
        return pictureMapper.countPictureByName(companyCode, pictureName);
    }

    @Override
    public PageInfo<CpPictureListVO> list(String companyCode, String pictureName, Long pictureGroupId, Integer pageNum, Integer pageSize) {
        //设置默认值
        if (pageNum == null) {
            pageNum = PageConstant.DEFAULT_PAGE_NUM;
        }
        if (pageSize == null) {
            pageSize = PageConstant.DEFAULT_PAGE_SIZE;
        }
        PageHelper.startPage(pageNum, pageSize);
        Page<CpPictureListDTO> page = pictureMapper.list(companyCode, pictureName, pictureGroupId);
        PageInfo<CpPictureListVO> pageInfo = new PageInfo<>();
        pageInfo.setPageNum(pageNum);
        pageInfo.setPageSize(pageSize);
        pageInfo.setTotal(page.getTotal());

        List<CpPictureListVO> voList = Lists.newArrayList();
        List<CpPictureListDTO> dtoList = page.getResult();
        for (CpPictureListDTO dto : dtoList) {
            CpPictureListVO vo = new CpPictureListVO();
            vo.setPictureName(dto.getPictureName());
            vo.setCompanyCode(dto.getCompanyCode());
            vo.setUrl(dto.getUrl());
            vo.setPictureId(dto.getPictureId());
            voList.add(vo);
        }
        pageInfo.setList(voList);
        return pageInfo;
    }


    /**
     * 获取图片名称类似的条数
     *
     * @param companyCode 商家编码
     * @param hasGroup    true属于分组，false不属于分组
     * @return Long(图片条数)
     * @throws ServiceException
     */
    @Override
    public long countPictureByCompany(String companyCode, boolean hasGroup) {
        return pictureMapper.countPictureByCompany(companyCode, hasGroup);
    }

    /**
     * 保存出节目场景背景图片
     *
     * @param pictureFile MultipartFile
     * @param request     HttpServletRequest
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Map<String, Object> uploadForSceneBackground(MultipartFile pictureFile, HttpServletRequest request) throws IOException {
        //获取用户的商家编码
        User loginUser = (User) request.getSession().getAttribute(RequestConstant.SESSION_KEY_USER);
        String companyCode = loginUser.getCompanyCode();
        //获取图片原始图片名
        String originalFilename = pictureFile.getOriginalFilename();
        //将MultipartFile转化为指定文件名的File
        File file = FileUtils.multipartFileConvertFile(pictureFile, originalFilename);
        //获取图片md5值
        String md5 = FileUtils.getFileMD5(file);
        //将图片上传至华为云
        String url = HuaWeiCloudUtils.uploadFile2HuaweiCloud(file, companyCode + "/program/scene/picture/");
        //把MultipartFile转化为File,会在本地创建图片，用完file后，需要删除
        if (file.exists()) {
            file.delete();
        }
        Map<String, Object> pictureMap = Maps.newHashMap();
        pictureMap.put("url", url);
        pictureMap.put("md5", md5);
        return pictureMap;
    }
}
